package feeinterface.protocol.req;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.ulwx.tool.ArrayUtils;
import com.ulwx.tool.CTime;
import com.ulwx.tool.CollectionUtils;
import com.ulwx.tool.DateTime;
import com.ulwx.tool.ObjectUtils;
import com.ulwx.tool.RandomUtils;
import com.ulwx.tool.StringUtils;
import com.ulwx.type.TInteger;
import com.ulwx.type.TResult;
import com.ulwx.type.TString;

import feeinterface.dao.BaseBlackCollectListDao;
import feeinterface.dao.BaseBlackListDao;
import feeinterface.dao.BaseBlackMyListDao;
import feeinterface.dao.BaseClientSmsCloseDao;
import feeinterface.dao.BaseDynamicRegularDao;
import feeinterface.dao.BaseImsiPhoneDao;
import feeinterface.dao.ChannelCloseProvincePhonePrexDao;
import feeinterface.dao.ChannelCycleDao;
import feeinterface.dao.ChannelDao;
import feeinterface.dao.ChannelFeeReqRespRecordDao;
import feeinterface.dao.ChannelIvrDao;
import feeinterface.dao.ChannelMoMatchDao;
import feeinterface.dao.ChannelOnlyUseOnceForImsiDao;
import feeinterface.dao.ChannelPhoneOverDayFeeDao;
import feeinterface.dao.ChannelPhoneOverMonthFeeDao;
import feeinterface.dao.ChannelProvinceMtCloseTimeLenDao;
import feeinterface.dao.ChannelServiceCoUserLimtDao;
import feeinterface.dao.ChannelSmsDao;
import feeinterface.dao.ChannelSpecialWithSpNoMoDao;
import feeinterface.dao.ChannelUserDayConsumeDao;
import feeinterface.dao.ChannelUserMonthConsumeDao;
import feeinterface.dao.ChannelUserSelectRecCloseInfoDao;
import feeinterface.dao.ChannelUserSelectRecordDao;
import feeinterface.dao.ChannelUserUseDao;
import feeinterface.dao.ChannelWapDao;
import feeinterface.dao.MobileDao;
import feeinterface.dao.MobileExtDao;
import feeinterface.dao.ServiceCoClosePacketDao;
import feeinterface.dao.ServiceCoDao;
import feeinterface.dao.ServiceCoOpenHourDao;
import feeinterface.dao.ServiceCoOpenProvinceDao;
import feeinterface.dao.ServiceCoUserDoublePrecisionDao;
import feeinterface.dao.ServiceCpDao;
import feeinterface.model.ChannelInfo;
import feeinterface.model.ChannelModel;
import feeinterface.modeldb.BaseClientSmsClose;
import feeinterface.modeldb.BaseDynamicRegular;
import feeinterface.modeldb.BaseImsiPhone;
import feeinterface.modeldb.Channel;
import feeinterface.modeldb.ChannelFeeReqRespRecord;
import feeinterface.modeldb.ChannelIvr;
import feeinterface.modeldb.ChannelMoMatch;
import feeinterface.modeldb.ChannelOnlyUseOnceForImsi;
import feeinterface.modeldb.ChannelServiceCoUserLimt;
import feeinterface.modeldb.ChannelSms;
import feeinterface.modeldb.ChannelSpecialWithSpNoMo;
import feeinterface.modeldb.ChannelUserDayConsume;
import feeinterface.modeldb.ChannelUserMonthConsume;
import feeinterface.modeldb.ChannelUserSelectRecCloseInfo;
import feeinterface.modeldb.ChannelUserSelectRecord;
import feeinterface.modeldb.ChannelWap;
import feeinterface.modeldb.Mobile;
import feeinterface.modeldb.MobileExt;
import feeinterface.modeldb.ServiceCo;
import feeinterface.modeldb.ServiceCoUserDoublePrecision;
import feeinterface.modeldb.ServiceCp;
import feeinterface.protocol.business.FeeUtil;
import feeinterface.protocol.business.ParseFetch;
import feeinterface.protocol.res.ChannelIVR;
import feeinterface.protocol.res.ChannelSMS;
import feeinterface.protocol.res.ChannelWAP;
import feeinterface.protocol.res.CmdAddr;
import feeinterface.protocol.res.ExtRespVar;
import feeinterface.protocol.res.FetchStep;
import feeinterface.protocol.res.Res010001;
import feeinterface.protocol.res.Res010005;
import feeinterface.protocol.res.Res010009;
import feeinterface.protocol.utils.Constants;
import feeinterface.utils.PhoneUtils;

/**
 * 
 * 业务流程名：付费接口 注释：此接口可以是客户端（手机）访问，也可以是第三方业务平台通过后台的方式访问 请求URL
 * ：http://<ip>:<port>/interface/exchange
 * 
 * @author 黄杰，孙超进
 * 
 */
public class Pro010001 extends ProExchange {

	private static Logger log = Logger.getLogger(Pro010001.class);

	@SuppressWarnings("all")
	@Override
	public Object genBean() throws Exception {

		long start = System.currentTimeMillis();
		if ("".equals(IMSI) || null == IMSI || StringUtils.isEmpty(IMSI)) {
			return FeeUtil.getFail(Constants.FeeStatus.ImsiIsEmpty);
		}
		TString carrier = new TString("未知");
		int[] areaIDs = this.getAreaID(this.Mobile, IMSI, this.SmsCenter,
				carrier);
		if (this.isFromServer()) {// 表明由服务器转发
			if (StringUtils.isEmpty(this.Mobile)) {// 如果手机号码为空，则使用请求端的送上来的运营商
				if (this.Carrier > 0) {
					carrier.setValue(Constants.getCarrierByCode(this.Carrier));
				}
			}
		}
		int provinceID = areaIDs[0];
		int cityID = areaIDs[1];

		Date curTime = CTime.getCurrentDateTime();
		// 注册用户
		Mobile mobile = new Mobile();
		mobile.setIMSI(this.IMSI);
		mobile.setRegistCarrier(carrier.getValue());
		mobile.setRegistCityID(cityID);
		mobile.setRegistExtVar(this.ExtVar);
		mobile.setRegistFeeMode(FeeMode);
		mobile.setRegistGatewayIP(this.getGateWayIP());
		mobile.setRegistGatewayKW(this.getGateWayKey());
		mobile.setRegistCountryID(Constants.Area.China);// 暂定为中国
		mobile.setRegistLibVer(this.Ver);
		mobile.setRegistMobile(this.Mobile);
		mobile.setRegistPacketID(this.PacketID);
		mobile.setRegistPlatform(this.Platform);
		mobile.setRegistProtocol(this.Protocol);
		mobile.setRegistProvinceID(provinceID);
		mobile.setRegistServiceCoID(COID);
		mobile.setRegistSmsCenter(this.SmsCenter);
		mobile.setRegistTime(curTime);
		mobile.setRegistVmVer(this.VmVer);

		MobileExt met = new MobileExt();

		met.setIMSI(this.IMSI);
		met.setLastCityID(cityID);
		met.setLastExtvar(this.ExtVar);
		met.setLastFeeMode(this.FeeMode);
		met.setLastRequestFeeTime(curTime);
		met.setLastGatewayIP(this.getGateWayIP());
		met.setLastGatewayKW(this.getGateWayKey());
		met.setLastLibVer(Ver);
		met.setLastPacketID(PacketID);
		met.setLastPlatform(Platform);
		met.setLastProvinceID(provinceID);
		met.setLastServiceCoID(COID);
		met.setLastVmVer(VmVer);

		boolean IsOldUser = false;
		int thisFee = this.PayFee;// 本次扣费金额
		boolean isBelongU6 = false;
		ServiceCo service = null;
		ServiceCp serviceCp = null;
		Res010001 res = new Res010001();

		Object result = res;
		TResult<Mobile> oldMoile = new TResult<Mobile>();
		try {
			try {

				// 1 判断合作是否存在,修改 孙超进 2012-02-16
				if (this.COID > 0) {
					service = ServiceCoDao.getBy(this.COID);

				}
				if (service == null) {
					return result = res = FeeUtil.getDefault(
							Constants.FeeStatus.ServiceCoDisabled, "("
									+ this.COID + ")在计费中心没有配置");

				}
				// 2 判断合作CP是否存在
				serviceCp = ServiceCpDao.getBy(this.COID);
				if (serviceCp == null) {
					return result = res = FeeUtil.getDefault(
							Constants.FeeStatus.ServiceCpNotFount, "根据合作("
									+ this.COID + ")在计费中心没有找到对应的CP");

				}
				if (serviceCp.getIsBelongU6() == 1) {
					isBelongU6 = true;
				} else {
					isBelongU6 = false;
				}

				IsOldUser = MobileDao.registIfnew(mobile, oldMoile);
				if (IsOldUser) {// 如果是老用户
					MobileExt meFromDb = MobileExtDao.getByIMSI(IMSI);
					met.setCurDayFee(meFromDb.getCurDayFee());
					met.setLastUseChannelTime(meFromDb.getLastUseChannelTime());
					met.setCurDayUseChannelCnt(meFromDb
							.getCurDayUseChannelCnt());
					met.setCurMonthFee(meFromDb.getCurMonthFee());
					met.setCurMonthUseChannelCnt(meFromDb
							.getCurMonthUseChannelCnt());
					met.setCurMonthUseChannelDayCnt(meFromDb
							.getCurMonthUseChannelDayCnt());
					met.setDayGetPhoneCnt(meFromDb.getDayGetPhoneCnt());
					met.setDoFee(meFromDb.getDoFee());

					met.setMonthGetPhoneCnt(meFromDb.getMonthGetPhoneCnt());
					met.setDayUpdateLib(meFromDb.getDayUpdateLib());
					met.setCurDayRequestCnt(meFromDb.getCurDayRequestCnt()+1);
					Date lastRequestFeeTime = meFromDb.getLastRequestFeeTime();
					if (lastRequestFeeTime == null) {
						met.setCurMonthRequestDayCnt(1);
					} else {
						DateTime dt = new DateTime(lastRequestFeeTime);
						DateTime dtcur = new DateTime(curTime);
						if (!dt.equalWithSameDay(dtcur)) {// 如果是不在同一天
							met.setCurMonthRequestDayCnt(meFromDb.getCurMonthRequestDayCnt()+1);
						}
					}

				} else {
					met.setCurDayFee(0);
					met.setCurDayUseChannelCnt(0);
					met.setCurMonthFee(0);
					met.setCurMonthUseChannelCnt(0);
					met.setCurMonthUseChannelDayCnt(0);
					met.setDayGetPhoneCnt(0);
					met.setDoFee(Constants.DoFee.NotUseChannel);
					met.setCurDayRequestCnt(1);
					met.setCurMonthRequestDayCnt(1);
					met.setMonthGetPhoneCnt(0);
					met.setDayUpdateLib(0);

				}

			} catch (Exception e) {
				log.error("", e);
				return result = res = FeeUtil.getDefault(
						Constants.FeeStatus.RegistMobileError,
						"" + e.getMessage() + "");
			}

			try {
				// 判断是否为客户端发送销量统计
				this.Mobile = PhoneUtils.getAdjustedPhone(this.Mobile);
				// 判断请求参数是否有手机号码
				if (StringUtils.hasText(this.Mobile)) {// 建立IMSI与手机号码的对应关系
					BaseImsiPhone bip = new BaseImsiPhone();
					bip.setCityID(cityID);
					bip.setIMSI(this.IMSI);
					bip.setPhone(this.Mobile);
					bip.setProvinceID(provinceID);
					bip.setUpdateTime(curTime);

					BaseImsiPhoneDao.Insert(bip);
				} else {
					BaseImsiPhone bp = BaseImsiPhoneDao.getPhoneBy(this.IMSI);
					if (bp != null) {
						this.Mobile = bp.getPhone();
					}
				}

			} catch (Exception e) {

				log.error("", e);
				return result = res = FeeUtil.getDefault(
						Constants.FeeStatus.UnknownError_1001, e.getMessage());

			}

			// 3 是否配置了测试绑定
			Res010001 resTest = FeeUtil.getBindTest(IMSI, Mobile, COID);
			if (resTest != null) {
				return result = res = resTest;
			}
			// 4 用户是否在北京市

			if (provinceID == Constants.BeiJin.ProviceID
					|| cityID == Constants.BeiJin.CityID) {
				return result = res = FeeUtil
						.getDefault(Constants.FeeStatus.IsBejin);
			}

			// 5 判断是否在我们自己的黑名单
			try {
				boolean isBlack = BaseBlackMyListDao.isBlackList(
						this.IMSI);
				if (isBlack) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.IsInMyBlackList);
				}

			} catch (Exception e) {
				log.error("", e); 
			}

			// 6 是否在SP黑名单
			try {
				boolean isBlack = BaseBlackListDao.isBlackList(this.Mobile,
						this.IMSI);
				if (isBlack) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.IsInBlackList);
				}

				isBlack = BaseBlackCollectListDao.isBlackList(IMSI);
				if (isBlack) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.IsInBlackList);
				}
			} catch (Exception e) {
				log.error("", e);
			}
			
			// 判断省份业务合作级别是否屏蔽
			if (service != null) {
				//则按省份合作级别配置进行屏蔽操作
				Mobile om = oldMoile.getValue();
				if (om != null ) {
					// 对新用户进行业务级别开通判断
					boolean pass = FeeUtil
							.decideByProvinceServiceClassCode(provinceID,
									service.getServiceClassCode());
					if (!pass) {
						return result = res = FeeUtil
								.getDefault(
										Constants.FeeStatus.CloseInProvinceServiceClass,
										"(" + this.COID + ")");
					}
				
				}

			}
			// ==============老用户则进行用户级别的过滤
			if (IsOldUser) {
				
				String serviceExtVar=StringUtils.trim(service.getExtVar());
				try{
					ServiceExtVar sev=ObjectUtils.fromJsonToObject(serviceExtVar, ServiceExtVar.class);
					if(sev!=null){
						Date starDate=null;
						try{
							starDate=CTime.parseDayDate(sev.getStartFeeDate());
						}catch(Exception ex){
							log.error("",ex);
						}
						int userCurDayReqMaxCnt=sev.getUserCurDayReqMaxCnt();
						int userCurMonthReqMaxDayCnt=sev.getUserCurMonthReqDayMaxCnt();
						if(met.getCurDayRequestCnt()>userCurDayReqMaxCnt){
							return result = res = FeeUtil
									.getDefault(Constants.FeeStatus.OverUserCurDayRequestCnt);
						}
						if(met.getCurMonthRequestDayCnt()>userCurMonthReqMaxDayCnt){
							return result = res = FeeUtil
									.getDefault(Constants.FeeStatus.OverUserCurMonthReqDayCnt);
						}
						if(starDate!=null){
						  if(starDate.after(CTime.getCurrentDateTime())){//NextAccessDate
							  res = FeeUtil
										.getDefault(Constants.FeeStatus.NoAccessData);
							  res.ExtRespVar="{NextAccessDate:\"" +sev.getStartFeeDate()+
							  		"\"}";
							  result=res;
							  return result;
						  }
						}
					}
				}catch(Exception ex){
					serviceExtVar="";
					log.error("",ex);
				}
				
				// 7 判断是否超过通道的日使用次数和通道的月使用次数

				int dayUseChannelCnt = met.getCurDayUseChannelCnt();// 用户通道的日使用次数
				int monthUseChannelDayCnt = met.getCurMonthUseChannelDayCnt();// 用户通道的月使用天数
				int monthUseChannelCnt = met.getCurMonthUseChannelCnt();// 用户通道的月使用的次数
				if (service.getUserDayFeeCntMax() > 0) {
					if (dayUseChannelCnt > service.getUserDayFeeCntMax()) {
						return result = res = FeeUtil
								.getDefault(Constants.FeeStatus.OverMaxDayUseChannelCnt);
					}
				}
				if (service.getUserMaxDayCntInMonth() > 0) {
					if (monthUseChannelDayCnt > service
							.getUserMaxDayCntInMonth()) {
						return result = res = FeeUtil
								.getDefault(Constants.FeeStatus.OverMaxMonthUseDayCnt);
					}
				}
				if (service.getUserMonthFeeCntMax() > 0) {
					if (monthUseChannelCnt > service.getUserMonthFeeCntMax()) {
						return result = res = FeeUtil
								.getDefault(Constants.FeeStatus.OverMaxMonthUseChannelCnt);
					}
				}
				// 8 判断此IMSI是否超过日限制
				int dayFee = met.getCurDayFee();
				// 9 算出今天最大可以扣除的金额
				int remainFee = Constants.MobileLimit.MaxDayFee - dayFee;
				if (remainFee <= 0) {// 表明不需要扣费
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.OverMaxDayFee);
				} else {
					if (remainFee < this.PayFee) {
						if (isBelongU6) {// 如果是U6扣费
							thisFee = remainFee;// 重新算出本次扣费金额
						} else {
							return result = res = FeeUtil
									.getDefault(Constants.FeeStatus.InsufficientDayBalance);
						}
					}
				}
				// 11 判断此IMSI是否超过月限制
				int monthFee = met.getCurMonthFee();
				remainFee = Constants.MobileLimit.MonthFee - monthFee;
				if (remainFee <= 0) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.OverMonthDayFee);
				} else {
					if (remainFee < this.PayFee) {
						if (isBelongU6) {// 如果是u6扣费
							thisFee = remainFee;// 重新算出本次扣费金额
						} else {
							return result = res = FeeUtil
									.getDefault(Constants.FeeStatus.InsufficientMonthBalance);
						}
					}
				}
			}

			// =============业务合作级别过滤

			// 12 判断请求的业务合作ID是否在屏蔽时段内
			boolean isCloseInHour = ServiceCoOpenHourDao
					.IsCloseInCurHour(this.COID);
			if (isCloseInHour) {// 在此时段被屏蔽
				return result = res = FeeUtil
						.getDefault(Constants.FeeStatus.ServiceCoColseInCurHour);
			}
			// 13 判断此合作ID是否在当前的省被屏蔽
			boolean isCloseInProvince = ServiceCoOpenProvinceDao
					.IsCloseInProvince(this.COID, provinceID);
			if (isCloseInProvince) {
				return result = res = FeeUtil
						.getDefault(Constants.FeeStatus.ServiceCoCloseInCurProvice);
			}
			// 14 判断此合作ID是否在当前的包被屏蔽
			boolean serviceCoCloseInPacket = ServiceCoClosePacketDao
					.packetCloseInServiceCo(this.COID, this.PacketID);
			if (serviceCoCloseInPacket) {
				return result = res = FeeUtil
						.getDefault(Constants.FeeStatus.ServiceCoCloseInPacket);
			}
			// ==============业务合作用户级别过滤

			// 算出单次扣费限额，如果为自由CP，则要判断传上来的SingleMaxFee参数，优先使用此参数，如果没有则使用CP合作配置的单次扣费限额
			int serviceCoSingleMaxFee = service.getSingleMaxFee();
			if (isBelongU6) {// 如果是u6扣费
				if (this.SingleMaxFee > 0) {
					serviceCoSingleMaxFee = this.SingleMaxFee;
				}
			}
			ChannelServiceCoUserLimt sul = ChannelServiceCoUserLimtDao.getBy(
					this.COID, IMSI);
			// 16 判断此次请求是否小于业务合作里配置的用户请求扣费间隔
			Date userLastFeeTime = sul.getLastFeeTime();
			if (userLastFeeTime != null) {
				Integer serviceCoFeeInterval = service.getUserFeeInterval();
				long figureInterval = CTime.getCurrentDateTime().getTime()
						- userLastFeeTime.getTime();
				// 如果扣费间隔等于"0"，表示不限制
				if (serviceCoFeeInterval > 0
						&& figureInterval < (serviceCoFeeInterval * 60 * 1000)) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.BetweenServiceCoUserFeeInterval);
				}
			}
			// 17 判断IMSI消费是否大于业务合作配置的允许单个用户达到的最大日限制
			int serviceUserDayFeeMax = service.getUserDayFeeMax();
			int remainFee = 0;
			if (serviceUserDayFeeMax > 0) {// 如果是0，则不限费！
				int dayFee = sul.getDayFee();
				remainFee = serviceUserDayFeeMax - dayFee;
				if (remainFee <= 0) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.OverServiceCoUserDayFeeMax);
				} else {
					if (remainFee < this.PayFee) {
						if (isBelongU6) {// 如果是u6扣费
							thisFee = remainFee;// 重新算出本次扣费金额
						} else {
							return result = res = FeeUtil
									.getDefault(Constants.FeeStatus.InsufficientServiceDayBalance);
						}
					}
				}
			}
			// 18 判断IMSI消费是否大于业务合作配置的允许单个用户达到的最大月限制
			int serviceUserMonthFeeMax = service.getUserMonthFeeMax();
			TInteger channelNoMoFee = new TInteger(0);
			if (serviceUserMonthFeeMax > 0) {// 如果是0，则不限费！
				int monthFee = sul.getMonthFee();
				int doubleFee = ServiceCoUserDoublePrecisionDao.getDoubleFee(
						IMSI, COID, channelNoMoFee); // 剩50%

				// 如果存在手机号码，说明存在IMSI与手机号码的匹配，这时候monthFee为真实的扣费数据
				if (StringUtils.hasText(this.Mobile)) {
					remainFee = serviceUserMonthFeeMax - monthFee - doubleFee;
				} else {// 如果没有手机号码，说明monthFee的值没有意义

					remainFee = serviceUserMonthFeeMax - doubleFee;
				}
				if (channelNoMoFee.getValue() > 0) { // 减去无上行通道的使用金额
					remainFee = remainFee - channelNoMoFee.getValue();
				}
				if (remainFee <= 0) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.OverServiceCoUserMonthFeeMax);
				} else {
					if (remainFee < this.PayFee) {
						if (isBelongU6) {// 如果是u6扣费
							thisFee = remainFee;// 重新算出本次扣费金额
						} else {
							return result = res = FeeUtil
									.getDefault(Constants.FeeStatus.InsufficientServiceMonthBalance);
						}
					}
				}
			}

			int prePolicyBit2 = FeeUtil.getBitValue(2, this.FeePolicy,
					isBelongU6);// 获取扣费策略的第二位（从右到左）

			// 孙超进 2012-02-15 判断 this.CanSupport是否是VM CanSupport@UDO
			// CanSupport模式，如果是这种模式，要进行合并
			String canSupport = StringUtils.trim(this.CanSupport);
			Integer[] vmCanSupportFeeTypes = null;
			Integer[] udoCanSupportFeeTypes = null;
			if (prePolicyBit2 == Constants.PrePolicy.PRE_VM_CAN_SUPPORT) {
				if (StringUtils.hasText(canSupport)) {
					String vmCanSupport = "";
					String udoCanSupport = "";
					if (canSupport.contains("@")) {
						String[] strs = StringUtils.split(canSupport, "@");
						if (strs.length >= 2) {
							vmCanSupport = StringUtils.trim(strs[0]);
							udoCanSupport = StringUtils.trim(strs[1]);
						} else {
							vmCanSupport = "";
							udoCanSupport = StringUtils.trim(strs[0]);
						}
						String[] vmCanSupportStrs = null;
						if (StringUtils.hasText(vmCanSupport)) {
							vmCanSupportStrs = vmCanSupport.split(",");
						}
						String[] udoCanSupportStrs = null;
						if (StringUtils.hasText(udoCanSupport)) {
							udoCanSupportStrs = udoCanSupport.split(",");
						}
						if (ArrayUtils.isNotEmpty(vmCanSupportStrs)) {
							vmCanSupportFeeTypes = ArrayUtils
									.StringArrayToIntegerArray(vmCanSupportStrs);
						}
						if (ArrayUtils.isNotEmpty(udoCanSupportStrs)) {
							udoCanSupportFeeTypes = ArrayUtils
									.StringArrayToIntegerArray(udoCanSupportStrs);
						}

						canSupport = canSupport.replaceAll("@", ",");
						canSupport = StringUtils.trimString(canSupport, ",");
						if (!canSupport.matches("\\d+( *, *\\d+)*")) {
							log.error("canSupport格式不对：" + canSupport);
							return result = res = FeeUtil.getDefault(
									Constants.FeeStatus.CanSupportFormatError,
									canSupport);
						}
					} else {
						return result = res = FeeUtil.getDefault(
								Constants.FeeStatus.CanSupportFormatError,
								canSupport);
					}
				}
			} else {
				// canSupport = canSupport.replaceAll("@", ",");
				// 验证canSupport
				if (!canSupport.matches("\\d+( *, *\\d+)*")) {
					log.error("canSupport格式不对：" + canSupport);
					return result = res = FeeUtil.getDefault(
							Constants.FeeStatus.CanSupportFormatError,
							canSupport);
				}

			}
			// ============根据业务合作里配置的业务级别和业务类型进行过滤
			// 19 ============通道级别过滤

			List<Channel> list = new ArrayList<Channel>();
			if (!isBelongU6) {// 如果是非自有CP
				canSupport = StringUtils.trim(service
						.getSupportChannelTypeCodeList());
				if (StringUtils.isEmpty(canSupport)) {// 如果为空的话
					canSupport = "0";// 表示全部支持
				}
			}
			if (StringUtils.hasText(canSupport)) {
				list = ChannelDao.selectChannelBy(service, provinceID, cityID,
						this.FeePolicy, canSupport, carrier.getValue(),
						serviceCoSingleMaxFee, this.Mobile, isBelongU6);
			}

			List<Integer> channelids = new ArrayList<Integer>();
			// 20 修改:黄敬锋2012-04-26================除去一个用户只能终身使用一次的通道 去除请求里包不支持的通道
			List<Integer> channels = ChannelOnlyUseOnceForImsiDao
					.getUseOneChannel(IMSI);
			for (int i = 0; i < list.size(); i++) {
				Channel ch = list.get(i);
				String extVar = StringUtils.trim(ch.getExtVar());
				if (StringUtils.hasText(extVar) && extVar.contains("{")
						&& extVar.contains("}")) {
					ChannelExtVar cev = ObjectUtils.fromJsonToObject(extVar,
							ChannelExtVar.class);
					String ClosePackets = StringUtils.trim(cev
							.getClosePackets());
					try {
						String[] pstrs = ArrayUtils.trim(ClosePackets
								.split(",|，"));
						if (ArrayUtils.isNotEmpty(pstrs)
								&& StringUtils.hasText(this.PacketID)) {
							if (ArrayUtils.contains(pstrs,
									StringUtils.trim(this.PacketID))) {
								// 此通道在请求的包里不能使用
								continue;
							}
						}
					} catch (Exception e3) {
						log.error("", e3);
					}
				}
				if (ch.getOnlyUseOnceForEverUser() == Constants.OnlyUseOnceForEverUser.YES) {
					if (channels.contains(ch.getChannelSno())) {// 此通道不能使用
						continue;
					}
				}

				channelids.add(ch.getChannelSno());
			}

			log.info("选择的通道1：" + ObjectUtils.toJsonString(channelids));
			if (CollectionUtils.isEmpty(channelids)) {
				return result = res = FeeUtil
						.getDefault(Constants.FeeStatus.FindeNoChannelRemoveOnlyOnce);
			}
			// 21 修改:黄敬锋2012-02-09================通道省份屏蔽号段过滤
			if (StringUtils.hasText(this.Mobile)) {
				channels = ChannelCloseProvincePhonePrexDao.getCloseInfo(
						provinceID, this.Mobile);
				if (channels.contains(0)) {// 是否包含通用，如果包含则说明此用户不能选择任何通道
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.FindeNoChannelRemoveScreenPrex);
				} else {
					channelids.removeAll(channels); // 移除屏蔽号段的通道
				}
			}
			log.info("选择的通道2--号段屏蔽后：" + ObjectUtils.toJsonString(channelids));
			if (CollectionUtils.isEmpty(channelids)) {
				return result = res = FeeUtil
						.getDefault(Constants.FeeStatus.FindeNoChannelRemoveScreenPrex);
			}
			// 22 ============除达到通道用户的最高日限额和月限额的通道
			List<ChannelModel> listnew = new ArrayList<ChannelModel>();
			List<Integer> listNewChids = new ArrayList<Integer>();

			// 找出通道用户日限和通道月限不能使用的通道
			if (StringUtils.hasText(this.Mobile)) {
				List<Integer> chOverDayList = ChannelPhoneOverDayFeeDao
						.getCantUseChannels(this.Mobile);
				List<Integer> chOverMonthList = ChannelPhoneOverMonthFeeDao
						.getCantUseChannels(this.Mobile);

				// 去重
				Set<Integer> chOverList = new HashSet<Integer>();
				chOverList.addAll(chOverDayList);
				chOverList.addAll(chOverMonthList);
				// 过滤不能使用的通道
				for (Integer ch : channelids) {
					if (chOverList.contains(ch)) {
						continue;
					}
					listNewChids.add(ch);
				}
			} else {
				listNewChids = channelids;
			}

			// 根据listNewChids查找通道
			listnew = ChannelDao.getChannelByRemoveOverDayMonthLimt(
					listNewChids.toArray(new Integer[0]), provinceID);

			if (CollectionUtils.isEmpty(listnew)) {
				return result = res = FeeUtil
						.getDefault(Constants.FeeStatus.FindNoChannelRemoveDayMonthMaxFee);
			}
			// 23 去除此用户选通道次数超过4，此用户上行率小于10%的通道，参数都可以配置(不行的通道),(统计时间为12小时内的)
			LinkedHashSet<ChannelModel> newChannelSetA = new LinkedHashSet<ChannelModel>();
			try {
				String channelCantUseListStr = ChannelUserUseDao
						.getUnUsedChannels(IMSI,
								Constants.FindChannelPolicy.OverUseCnt,
								Constants.FindChannelPolicy.MoRate);
				log.debug("==================不行的通道:" + channelCantUseListStr);
				if (StringUtils.hasText(channelCantUseListStr)) {
					String[] strs = channelCantUseListStr.split(",");
					if (ArrayUtils.isNotEmpty(strs)) {
						Integer[] channelIdCantUse = ArrayUtils
								.StringArrayToIntegerArray(strs);
						for (int i = 0; i < listnew.size(); i++) {
							ChannelModel c = listnew.get(i);
							if (ArrayUtils.indexOf(channelIdCantUse,
									c.getChannelSno()) > -1) {
								continue;
							} else {
								newChannelSetA.add(c);
							}
						}
					}
				} else {
					newChannelSetA.addAll(listnew);
				}

			} catch (Exception e) {
				log.error("", e);
			}

			// 24 过滤后的通道根据省份权重排序(已经在)，此步骤已经在19步做过

			// 25 去除不推荐使用的通道（用户选通道次数减去上行次数至少大于2的通道）
			LinkedHashSet<ChannelModel> newChannelSetB = new LinkedHashSet<ChannelModel>();
			if (CollectionUtils.isNotEmpty(newChannelSetA)) {

				try {
					String channelNotCommendListStr = ChannelUserUseDao
							.getNotCommendChannels(IMSI,
									Constants.FindChannelPolicy.SubUseCnt);
					log.debug("============不推荐使用的通道:"
							+ channelNotCommendListStr);
					if (StringUtils.hasText(channelNotCommendListStr)) {
						String[] strs = channelNotCommendListStr.split(",");
						if (ArrayUtils.isNotEmpty(strs)) {
							Integer[] channelNotCommend = ArrayUtils
									.StringArrayToIntegerArray(strs);

							for (ChannelModel ch : newChannelSetA) {
								if (ArrayUtils.indexOf(channelNotCommend,
										ch.getChannelSno()) > -1) {
									continue;
								} else {
									newChannelSetB.add(ch);
								}
							}
						}
					} else {
						newChannelSetB = newChannelSetA;
					}

				} catch (Exception e) {
					log.error("", e);
				}
			}
			// 26 判断集合B是否为空，如果为空使用集合A
			LinkedHashSet<ChannelModel> channelSet = new LinkedHashSet<ChannelModel>();
			if (CollectionUtils.isEmpty(newChannelSetB)) {
				channelSet = newChannelSetA;
			} else {
				channelSet = newChannelSetB;
			}
			if (CollectionUtils.isEmpty(channelSet)) {
				return result = res = FeeUtil
						.getDefault(Constants.FeeStatus.FindNoChannelAfterFilterCantUse);
			}
			List<ChannelModel> channelList = new ArrayList<ChannelModel>(
					channelSet);
			// =====根据扣费金额和通道的单次发送条数，通道费率进行过滤筛选通道
			int mustPayFee = thisFee; // 用户需要扣的钱
			// 如果用户需要扣1元，则找出1元的通道
			List<ChannelModel> channelListFor100 = new ArrayList<ChannelModel>();
			if (mustPayFee == 100) {
				for (ChannelModel chm : channelList) {
					if (chm.getFeeCode() == 100) {
						channelListFor100.add(chm);
					}
				}
				if (!isBelongU6) {// 如果是别人的通道
					// 如果是别人的通道
					// 重新对channelArrays赋值
					if (CollectionUtils.isNotEmpty(channelListFor100)) {
						channelList = channelListFor100;// 让第三方一元的扣费在一元的通道里选择
					} else {
						return result = res = FeeUtil
								.getDefault(Constants.FeeStatus.FindNoChannelWithNoOneYuanChannelForThirdPart);
					}
				}
			}
			List<ChannelInfo> finalSelectChannels = new ArrayList<ChannelInfo>();
			// ===================通道选择的准备工作==========================

			List<ChannelModel> channelSMSList = new ArrayList<ChannelModel>();
			List<ChannelModel> channelIVRList = new ArrayList<ChannelModel>();
			List<ChannelModel> channelWAPList = new ArrayList<ChannelModel>();
			List<ChannelModel> vmSupportChannelList = new ArrayList<ChannelModel>();
			List<ChannelModel> udoSupportChannelList = new ArrayList<ChannelModel>();
			// 孙超进 2012-02-15
			int policyFlag = 0;

			String useCanSupport = Constants.UseCanSupport.NONE;

			if (prePolicyBit2 != Constants.PrePolicy.DEFAULT) {// 如果不为默认

				if (prePolicyBit2 == Constants.PrePolicy.PRE_VM_CAN_SUPPORT) {// 优先使用VM
																				// CanSupport选择通道算法
					// 孙超进 2012-02-15
					for (int i = 0; i < channelList.size(); i++) {
						ChannelModel ch = channelList.get(i);

						if (vmCanSupportFeeTypes != null
								&& ArrayUtils.indexOf(vmCanSupportFeeTypes,
										ch.getChannelTypeCode()) > -1) {
							vmSupportChannelList.add(ch);

						}
						if (udoCanSupportFeeTypes != null
								&& ArrayUtils.indexOf(udoCanSupportFeeTypes,
										ch.getChannelTypeCode()) > -1) {
							udoSupportChannelList.add(ch);

						}
					}
					channelList.clear();
					if (vmSupportChannelList.size() > 0) {
						policyFlag = 1;
						channelList.addAll(vmSupportChannelList);
						useCanSupport = Constants.UseCanSupport.VM;
					} else if (udoSupportChannelList.size() > 0) {
						policyFlag = 2;
						channelList.addAll(udoSupportChannelList);
						useCanSupport = Constants.UseCanSupport.UDO;
					} else {
						useCanSupport = Constants.UseCanSupport.NONE;
					}

				} else if (prePolicyBit2 == Constants.PrePolicy.PRE_SMS) {// 单一通道类型选择策略
					for (int i = 0; i < channelList.size(); i++) {
						ChannelModel ch = channelList.get(i);
						if (ch.getChannelBigType() == Constants.ChannelBigType.SMS) {
							channelSMSList.add(ch);
						} else if (ch.getChannelBigType() == Constants.ChannelBigType.IVR) {
							channelIVRList.add(ch);
						} else if (ch.getChannelBigType() == Constants.ChannelBigType.WAP) {
							channelWAPList.add(ch);
						}
					}
					// 清除channelList
					channelList.clear();
					if (channelSMSList.size() > 0) {
						channelList.addAll(channelSMSList);
						policyFlag = 3;
					} else if (channelIVRList.size() > 0) {
						channelList.addAll(channelIVRList);
						policyFlag = 4;
					} else if (channelWAPList.size() > 0) {
						channelList.addAll(channelWAPList);
						policyFlag = 5;
					}
				} else {

					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.FeePolicyBit2Error);

				}
			}

			// 按通道的优先级排序
			Collections.sort(channelList,
					Collections.reverseOrder(new Comparator<ChannelModel>() {

						public int compare(ChannelModel o1, ChannelModel o2) {
							return o1.getWeight() - o2.getWeight();
						}
					}));

			// 备有通道选择，如果是U6通道，则可以扣费超原定50%;
			List<ChannelModel> channelBackList = new ArrayList<ChannelModel>();
			// 27 选通道,优先SMS和IVR通道，如果未选择到通道，则增加WAP通道继续查找
			int whilelCnt = 0, realFee = 0;

			while (true && whilelCnt < 100 && channelList.size() > 0) {

				whilelCnt++;
				int[] weights = new int[channelList.size()];
				int total = 0;
				for (int i = 0; i < channelList.size(); i++) {
					total = total + channelList.get(i).getWeight();
					weights[i] = total;
				}
				int random = RandomUtils.nextInt(total);
				int index = -1;
				for (int i = 0; i < channelList.size(); i++) {
					int wh = weights[i];
					if (random < wh) {
						index = i;
						break;
					}
				}
				if (index == -1) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.UnknownError_1000);
				}
				// 选中index索引位置的通道
				Channel ch = channelList.get(index);
				int singleMaxCnt = ch.getSingleMaxCnt();
				int feeCode = ch.getFeeCode();
				int chDayMaxFee = ch.getUserDayMaxFee();
				int chMonthMaxFee = ch.getUserMonthMaxFee();
				int canFee = mustPayFee;
				int feeCnt = 0;
				boolean noMoChannel = false;
				if (chDayMaxFee > 0 || chMonthMaxFee > 0) {// 判断是否为无上行通道
					TResult<ChannelSpecialWithSpNoMo> cswn = new TResult<ChannelSpecialWithSpNoMo>();
					noMoChannel = ChannelSpecialWithSpNoMoDao.isNoMo(
							ch.getChannelSno(), cswn);
				}
				if (chDayMaxFee > 0) {// 要进行通道用户日限处理
					// 重新计算这个用户在这条通道上还可以扣除的费用
					TInteger noMoFee = new TInteger(0);
					TInteger doubleFee = new TInteger(0);
					int userChannelDayFee = ChannelUserDayConsumeDao
							.getChannelUserDayFee(this.IMSI,
									ch.getChannelSno(), noMoFee, doubleFee);

					if (noMoChannel) {// 如果是无上行通道
						chDayMaxFee = chDayMaxFee - noMoFee.getValue();
					} else {// 有上行通道

						if (StringUtils.hasText(this.Mobile)) {// 如果是有匹配的
							chDayMaxFee = chDayMaxFee - userChannelDayFee;// 这个通道上还能使用的金额
						} else {// 如果没有匹配，则使用通道双精金额
							chDayMaxFee = chDayMaxFee - doubleFee.getValue();
						}
					}

					if (chDayMaxFee > 0) {
						if (canFee > chDayMaxFee) {// 2 》8
							canFee = chDayMaxFee;
						}
					} else {// 如果扣超，则本条通道不算
						canFee = 0;
					}
				}

				if (chMonthMaxFee > 0 && canFee > 0) {// 要进行通道用户的月限处理
					TInteger noMoFee = new TInteger(0);
					TInteger doubleFee = new TInteger(0);
					int userChannelMonthFee = ChannelUserMonthConsumeDao
							.getChannelUserMonthFee(this.IMSI,
									ch.getChannelSno(), noMoFee, doubleFee);
					if (noMoChannel) {// 如果是无上行通道
						chMonthMaxFee = chMonthMaxFee - noMoFee.getValue();
					} else {// 有上行通道
						if (StringUtils.hasText(this.Mobile)) {// 如果是有匹配的
							chMonthMaxFee = chMonthMaxFee - userChannelMonthFee;
						} else {
							chMonthMaxFee = chMonthMaxFee
									- doubleFee.getValue();
						}
					}

					if (chMonthMaxFee > 0) {// 这个月还可以使用的金额
						if (canFee > chMonthMaxFee) {
							canFee = chMonthMaxFee;
						}
					} else {// 如果扣超，则本条通道不算
						canFee = 0;
					}
				}
				// 算出本通道可以发送到条数
				feeCnt = canFee / feeCode;
				// 如果发送条数大于0，表示此通道可用添加到队列
				if (feeCnt > 0) {
					// 限制通道单次最大发送条数
					if (singleMaxCnt > 0 && feeCnt > singleMaxCnt) {
						feeCnt = singleMaxCnt;
					}
					ChannelInfo cinf = new ChannelInfo();
					cinf.setChannel(ch);
					cinf.setSendCnt(feeCnt);
					realFee = realFee + feeCode * feeCnt;// 通道实际扣费金额
					finalSelectChannels.add(cinf);
					channelList.remove(index);// 下次选通道排除此通道
					mustPayFee = mustPayFee - feeCnt * (int) feeCode;
					if (mustPayFee <= 0) {// 达到请求扣费金额则终止
						break;
					}
					if (this.ChannelMaxNum > 0) {// 限制请求的最大通道条数，如果值为0表示不限制
						if (finalSelectChannels.size() >= this.ChannelMaxNum) {
							break;
						}
					}
				} else {
					channelList.remove(index);// 下次选通道排除此通道
					// ===特殊处理，channelBackList作为U6选通道的备选
					if (channelBackList != null && isBelongU6) {
						channelBackList.add((ChannelModel) ch);
					}
				}
				// ===特殊处理，如果是U6通道并且还没有扣够，则可以扣费超原定50%
				if (channelBackList != null && isBelongU6
						&& channelList.size() <= 0 && realFee < thisFee) {
					channelList.addAll(channelBackList);
					channelBackList = null;
					mustPayFee = mustPayFee + thisFee / 2;// 如果是U6通道，则可以扣费超原定50%
					log.debug("为U6通道继续查找合适的通道组合！");
				}
				// 如果是非默认选通道策略，并且到循环结束时也没有选择到任何通道
				if (prePolicyBit2 != Constants.PrePolicy.DEFAULT
						&& finalSelectChannels.size() <= 0
						&& channelList.size() <= 0) {
					if (prePolicyBit2 == Constants.PrePolicy.PRE_VM_CAN_SUPPORT) {
						// ===如果没有查找到vm支持的通道，那么就查找udo支持的通道
						if (policyFlag == 1) { // vm没有成功选到通道，再根据udo支持的通道来选择通道
							if (null != udoSupportChannelList
									&& udoSupportChannelList.size() > 0) {
								channelList.addAll(udoSupportChannelList);
								channelBackList = new ArrayList<ChannelModel>();
								useCanSupport = Constants.UseCanSupport.UDO;

							} else {
								useCanSupport = Constants.UseCanSupport.NONE;
							}
						}
					} else if (prePolicyBit2 == Constants.PrePolicy.PRE_SMS) {
						// 优先SMS，如果没有SMS则选择IVR，如果SMS和IVR都没有，则选择WAP
						if (policyFlag == 3) {
							if (null != channelIVRList
									&& channelIVRList.size() > 0) {
								channelList.addAll(channelIVRList);
								channelBackList = new ArrayList<ChannelModel>();
								channelIVRList = null;
								policyFlag = 4;
							}
						} else if (policyFlag == 4) {
							if (null != channelWAPList) {
								channelList.addAll(channelWAPList);
								channelBackList = new ArrayList<ChannelModel>();
								channelWAPList = null;
							}
						}

					} else {
						return result = res = FeeUtil
								.getDefault(Constants.FeeStatus.FeePolicyBit2Error);
					}
					// 按通道的优先级排序
					if (CollectionUtils.isNotEmpty(channelList)) {
						Collections.sort(channelList, Collections
								.reverseOrder(new Comparator<ChannelModel>() {
									public int compare(ChannelModel o1,
											ChannelModel o2) {
										return o1.getWeight() - o2.getWeight();
									}
								}));
					}
				}

			}
			if (CollectionUtils.isNotEmpty(finalSelectChannels)) {

				// 28 查找通道的扩展信息信息
				for (int i = 0; i < finalSelectChannels.size(); i++) {
					ChannelInfo cinfo = finalSelectChannels.get(i);
					Channel ch = cinfo.getChannel();
					// 去除用户72小时只能使用一次的通道
					if(ch.getOnlyUseOnceForEverUser()==Constants.OnlyUseOnceForEverUser.Hour72){
					   boolean isBetween72Hours=
							   ChannelUserSelectRecordDao.isBetween72Hours(this.IMSI, ch.getChannelSno());
					   if(isBetween72Hours){//在72小时之内
						   finalSelectChannels.remove(i);
						   i--;//回退
						   continue;
					   }
					}
					if (ch.getChannelBigType() == Constants.ChannelBigType.SMS) {
						ChannelSms chsms = ChannelSmsDao.getBy(ch
								.getChannelSno());
						cinfo.setChanelExtInfo(chsms);
					} else if (ch.getChannelBigType() == Constants.ChannelBigType.WAP) {
						ChannelWap chswap = ChannelWapDao.getBy(ch
								.getChannelSno());
						cinfo.setChanelExtInfo(chswap);
					} else if (ch.getChannelBigType() == Constants.ChannelBigType.IVR) {
						ChannelIvr chivr = ChannelIvrDao.getBy(ch
								.getChannelSno());
						cinfo.setChanelExtInfo(chivr);
					} else {
						return result = res = FeeUtil
								.getDefault(Constants.FeeStatus.UnknowError_1002);
					}
				}
			}
			if (this.QueryChannel == Constants.QueryChannel.Query) {
				// 最后找到的通道在finalSelectChannels中,判断是否为空
				if (CollectionUtils.isEmpty(finalSelectChannels)) {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.FindNoChannelByFeeCodeAndSingleMaxCnt);
				}
				// 如果是通道查询，则直接返回通道情况，无需插入或更新记录
				return result = res = FeeUtil.getQuery(finalSelectChannels,
						realFee, provinceID, service, this.PhoneFactoryName,
						carrier.getValue());
			}

			// 如果业务合作未发手机号，并且虚拟机版本号小于21，为了兼容旧系统只发销量统计

			List<ChannelSMS> smsGetPhonelist = new ArrayList<ChannelSMS>();
			if ((null == this.Mobile || "".equals(this.Mobile.trim()))
					&& this.VmVer < 21 & this.Ver == 0) {// 孙超进
				// 2012-02-16,VmVer大于=21可以做销量统计跳转
				int bit8 = FeeUtil.getBitValue(8, this.FeePolicy, isBelongU6);
				if (bit8 == Constants.GetPhonePolicy.Need) {
					ChannelSMS sms = new ChannelSMS();
					Pro010005 pro010005 = new Pro010005();
					pro010005.setRequest(this.getRequest());
					pro010005.COID = this.COID;
					pro010005.IMSI = this.IMSI;
					pro010005.PacketID = this.PacketID;
					pro010005.Platform = this.Platform;
					pro010005.SmsCenter = this.SmsCenter;
					pro010005.Ver = this.Ver;
					pro010005.VmVer = this.VmVer;
					Res010005 obj = (Res010005) pro010005.genBean();
					if (obj.Status == Constants.Status.SUCCESS) {
						met.setMonthGetPhoneCnt(met.getMonthGetPhoneCnt() + 1);
						met.setDayGetPhoneCnt(met.getDayGetPhoneCnt() + 1);
						sms.ChannelID = 0;
						sms.SmsFeeCode = 0;
						sms.SmsFeeCmd = obj.SMSContent;
						sms.SmsFeePort = obj.SMSCatPort;
						sms.SendCnt = 1;// 发送次数等于一
						smsGetPhonelist.add(sms);

					}
				}

			}
			// 29 组装协议响应响应
			res.Protocol = "010001";
			if (CollectionUtils.isNotEmpty(finalSelectChannels)) {
				res.FeeStatus = Constants.FeeStatus.SuccussReturnChannel;// 正常返回通道
			} else {// 如果为空
				if (smsGetPhonelist.size() > 0) {// 如果选择的通道为空，并且包含销量统计，即只包含销量统计
					res.FeeStatus = Constants.FeeStatus.SuccussReturnGetPhone;// 返回销量统计
				} else {
					return result = res = FeeUtil
							.getDefault(Constants.FeeStatus.FindNoChannelByFeeCodeAndSingleMaxCnt);
				}

			}

			res.Status = Constants.Status.SUCCESS;
			res.Message = "成功";

			res.FeeID = RandomUtils.genUUID();
			res.ThisFee = realFee;// 本次扣费实际扣的钱（分）

			List<ChannelSMS> smslist = new ArrayList<ChannelSMS>();
			List<ChannelWAP> waplist = new ArrayList<ChannelWAP>();
			List<ChannelIVR> ivrlist = new ArrayList<ChannelIVR>();

			// 增加获取手机号码指令
			smslist.addAll(smsGetPhonelist);

			// 30设置双精匹配表ChannelMoMatch的左侧数据
			ChannelMoMatch cmm = new ChannelMoMatch();
			cmm.setLCityID(cityID);
			cmm.setLExtVar(this.ExtVar);
			cmm.setLFeeID(res.FeeID);
			cmm.setLFeeMode(this.FeeMode);
			cmm.setLIMSI(this.IMSI);
			cmm.setLLibVer(this.Ver);
			cmm.setLMobile(this.Mobile);
			cmm.setLPacketID(this.PacketID);
			cmm.setLPlatform(this.Platform);
			cmm.setLProvinceID(provinceID);
			cmm.setLServiceCoID(this.COID);
			cmm.setLTime(curTime);
			cmm.setLVmVer(this.VmVer);
			// 31增加一个ChannelUserSelectRecord表来记录成功选通道的详情
			ChannelUserSelectRecord cur = new ChannelUserSelectRecord();
			cur.setCarrier(carrier.getValue());
			cur.setCityID(cityID);
			cur.setCreateTime(curTime);
			cur.setFeeID(res.FeeID);
			cur.setGateIP(this.getGateWayIP());
			cur.setGatewayKeyword(this.getGateWayKey());
			cur.setIMSI(this.IMSI);
			cur.setLibVer(this.Ver);
			cur.setProvinceID(provinceID);
			cur.setServiceCoID(this.COID);
			cur.setSmsCenter(this.SmsCenter);
			cur.setVmVer(this.VmVer);
			cur.setExtVar(this.ExtVar);
			cur.setFeeMode(this.FeeMode);
			cur.setPlatform(this.Platform);
			cur.setPacketID(this.PacketID);
			// 32用户使用通道日消费记录
			ChannelUserDayConsume cudc = new ChannelUserDayConsume();
			cudc.setIMSI(this.IMSI);
			cudc.setProvinceID(provinceID);
			cudc.setServiceCoID(this.COID);
			cudc.setFeeDate(curTime);
			cudc.setFeeTotal(0);
			// 33用户使用通道月消费记录
			ChannelUserMonthConsume cumc = new ChannelUserMonthConsume();
			cumc.setIMSI(this.IMSI);
			cumc.setProvinceID(provinceID);
			cumc.setServiceCoID(this.COID);
			cumc.setStatMonth(CTime.parseDayDate(CTime
					.getFirstDayOfMonth(curTime)));
			cumc.setLastUpdateTime(curTime);
			cumc.setFeeTotal(0);
			// 34业务合作用户双精使用金额（月清）
			ServiceCoUserDoublePrecision scd = new ServiceCoUserDoublePrecision();
			scd.setIMSI(IMSI);
			scd.setServiceCoID(COID);
			scd.setUpdateTime(curTime);
			int channelUseCnt = 0;

			// 修改：孙超进 2012-02-16，正常的选通道
			for (int i = 0; i < finalSelectChannels.size(); i++) {
				ChannelInfo cinfo = finalSelectChannels.get(i);
				Channel ch = cinfo.getChannel();
				int sendCnt = cinfo.getSendCnt();// 次数
				channelUseCnt = channelUseCnt + sendCnt;
				Object chex = cinfo.getChanelExtInfo();
				// 35 更新ChannelServiceCoUserLimt
				ChannelServiceCoUserLimtDao.insertUpdateLastFeeTime(curTime,
						ch.getChannelSno(), this.COID, this.IMSI);
				// 判断是否为无上行通道
				boolean noMoChannel = false;
				TResult<ChannelSpecialWithSpNoMo> cswn = new TResult<ChannelSpecialWithSpNoMo>();
				noMoChannel = ChannelSpecialWithSpNoMoDao.isNoMo(
						ch.getChannelSno(), cswn);

				if (!noMoChannel) {// 如果为有上行通道则更新
					// 36 更新ChannelUserUse
					ChannelUserUseDao.updateUserUseByImsi(this.IMSI,
							ch.getChannelSno(), sendCnt, curTime);
				}
				// 设置双精匹配表ChannelMoMatch的左侧数据
				cmm.setLChannelBigType(ch.getChannelBigType());
				cmm.setLChannelID(ch.getChannelSno());
				cmm.setLChannelTypeCode(ch.getChannelTypeCode());

				// 记录成功选通道的详情
				cur.setChannelBigType(ch.getChannelBigType());
				cur.setChannelID(ch.getChannelSno());
				cur.setChannelTypeCode(ch.getChannelTypeCode());
				cur.setFeeTipInfo(ch.getFeeTipInfo());
				cur.setFeeCode(ch.getFeeCode());
				// 双精金额（单位分），计费接口选通道累加，通道接口减去

				// scd.setDoubleFee((int)(ch.getFeeCode() * sendCnt *0.5));
				scd.setDoubleFee((int) (ch.getFeeCode() * sendCnt));
				scd.setChannelNoMoFee(ch.getFeeCode() * sendCnt);

				if (ch.getChannelBigType() == Constants.ChannelBigType.SMS) {
					ChannelSms chsms = (ChannelSms) chex;
					// 解析短彩类通道，进行拼装！
					BaseDynamicRegular bsreg = null;
					CmdAddr[] ca = ParseFetch.parse(ch.getSendCmd(),
							ch.getDestAddr(), sendCnt,
							chsms.getSmsExtCmdAddrList());

					if (noMoChannel) {// 如果为无上行通道,只更新无上行通道使用金额
						Integer ajustFee = (int) (scd.getChannelNoMoFee() * cswn
								.getValue().getNoMoRate());
						// Integer ajustFee=(int)(scd.getChannelNoMoFee());
						float ajrate = ((float) ch.getSettlementPrice())
								/ ch.getFeeCode();
						Integer settleFee = (int) (ajustFee * ajrate);

						// scd.setChannelNoMoFee(ajustFee);
						ServiceCoUserDoublePrecisionDao.sumWithNoMo(scd);
						// 如果为无上行通道要更新通道周期表
						ChannelCycleDao.updateCnt(ch.getChannelSno(), ajustFee,
								settleFee);
						// 要更新ChannelUserDayConsume表里的FeeTotal字段
						// cudc.setFeeTotal(ch.getFeeCode() * sendCnt);
						cudc.setNoMoChannelFee(ch.getFeeCode() * sendCnt);
						// 要更新ChannelUserMonthConsume表里的FeeTotal字段
						// cumc.setFeeTotal(ch.getFeeCode() * sendCnt);
						cumc.setNoMoChannelFee(ch.getFeeCode() * sendCnt);

					} else { // 有上行通道，只在手机号码没有找到的情况下，才更新双精使用金额
						if (StringUtils.isEmpty(this.Mobile)) {// 算作双精使用次数
							ServiceCoUserDoublePrecisionDao.Cumsum(scd);
							cudc.setDoubleFee(ch.getFeeCode() * sendCnt);
							cumc.setDoubleFee(ch.getFeeCode() * sendCnt);
						} else {
							cudc.setDoubleFee(0);
							cumc.setDoubleFee(0);
						}
					}
					// 插入匹配表，只对有上行通道有意义
					if (!noMoChannel) {

						// if (chsms.getDoublePrecision() ==
						// Constants.DoublePrecision.YES) {// 双精通道
						for (int n = 0; n < sendCnt; n++) {
							ChannelMoMatchDao.insert(cmm);
						}
						// }
					}
					for (int j = 0; j < ca.length; j++) {
						ChannelSMS sms = new ChannelSMS();
						sms.ChannelID = ch.getChannelSno();
						sms.IsDouble = chsms.getDoublePrecision();
						if (sms.IsDouble == Constants.DoublePrecision.NO) {
							// 如果是模糊通道则加入COID
							sms.SmsFeeCmd = ca[j].Cmd + this.COID;
							// ChSmsLen（模糊指令的最大长度）
							sms.ExtSmsVar = "ChSmsLen=" + chsms.getSmsLen();
						} else {
							sms.SmsFeeCmd = ca[j].Cmd;// 双精通道
						}
						if (StringUtils.hasText(sms.ExtSmsVar)) {
							sms.ExtSmsVar = sms.ExtSmsVar + "@@"
									+ ca[j].extSmsVar;
						} else {
							sms.ExtSmsVar = ca[j].extSmsVar;
						}
						if (StringUtils.hasText(sms.ExtSmsVar)) {
							if (noMoChannel) {
								sms.ExtSmsVar = sms.ExtSmsVar + "@@" + "CT=1";
								sms.ExtSmsVar = sms.ExtSmsVar + "@@FeeCode="
										+ ch.getFeeCode();
							} else {
								sms.ExtSmsVar = sms.ExtSmsVar + "@@" + "CT=0";
								sms.ExtSmsVar = sms.ExtSmsVar + "@@FeeCode="
										+ ch.getFeeCode();
							}
						}
						sms.FeeTipInfo = ch.getFeeTipInfo();
						sms.FeeType = ch.getChannelTypeCode();
						// 如果长度为1，说明不是双短信通道,则发送次数根据计算所得;1065双短信通道,发送次数为1
						sms.SendCnt = ca.length == 1 ? sendCnt : 1;
						sms.SendInterval = ch.getClientSendInterval();
						sms.SmsFeeCode = ch.getFeeCode();
						sms.SmsFeePort = ca[j].Addr;
						int validateFlag = chsms.getValidateFlag();
						sms.SmsValidateFlag = (byte) validateFlag;
						if (validateFlag == Constants.ValidateSmsType.NeedClientValidate
								|| validateFlag == Constants.ValidateSmsType.NeedServerValidate) {

							List<BaseDynamicRegular> listbdr = BaseDynamicRegularDao
									.getDyRegularBy(provinceID,
											ch.getChannelSno(),
											carrier.getValue());
							if (listbdr != null && listbdr.size() > 0) {
								bsreg = listbdr.get(0);
							} else {
								throw new Exception("省份id=" + provinceID
										+ "动态验证规则没有配置");
							}
							if (bsreg != null) {
								sms.SmsStartFlag = StringUtils.trim(bsreg
										.getStartFlag());
								sms.SmsEndFlag = StringUtils.trim(bsreg
										.getEndFlag());
							} else {
								sms.SmsStartFlag = "";
								sms.SmsEndFlag = "";
							}
						} else {
							sms.SmsValidateFlag = (byte) Constants.ValidateSmsType.NoNeedValidate;
							sms.SmsStartFlag = "";
							sms.SmsEndFlag = "";
						}
						smslist.add(sms);

					}
					cur.setSendCmd(ch.getSendCmd());
					cur.setDestAddr(ch.getDestAddr());
					cur.setSendCnt(sendCnt);
					cur.setUseCnt(sendCnt);
					cur.setSendInterval(ch.getClientSendInterval());
					ChannelUserSelectRecordDao.insert(cur);

					cudc.setChannelID(ch.getChannelSno());
					cudc.setUseCnt(sendCnt);

					cumc.setChannelID(ch.getChannelSno());
					cumc.setUseCnt(sendCnt);

				} else if (ch.getChannelBigType() == Constants.ChannelBigType.WAP) {
					ChannelWAP wap = new ChannelWAP();
					ChannelWap chwap = (ChannelWap) chex;
					// 根据前置关联操作的定义，虚拟成通道
					String OtherFechJsonStr = StringUtils.trim(chwap
							.getOtherFechJsonStr());
					if (StringUtils.hasText(OtherFechJsonStr)
							&& OtherFechJsonStr.startsWith("[")
							&& OtherFechJsonStr.endsWith("]")) {
						/**
						 * 其他的非关联的模拟用户操作的步骤，格式为: [ { "url": 'url1' , "steps": [{
						 * "findkey":'key1', "endkey":'ekey1' } , { ... }, ... ]
						 * } , { "url": 'url2' , "steps": [{ "findkey":'key1',
						 * "endkey":'ekey1' } , { ... }, ... ] } , .... ]
						 */
						try {
							List<Map<String, Object>> OtherFechJsonBean = (List<Map<String, Object>>) ObjectUtils
									.fromJsonTobject(OtherFechJsonStr);
							for (int m = 0; m < OtherFechJsonBean.size(); m++) {
								Map<String, Object> relationOperation = OtherFechJsonBean
										.get(m);
								String entryUrl = (String) relationOperation
										.get("url");
								List<Map<String, Object>> steps = (List<Map<String, Object>>) relationOperation
										.get("steps");
								if (steps == null)
									steps = new ArrayList<Map<String, Object>>();
								// 虚拟成通道
								ChannelWAP virtualWapChannel = new ChannelWAP();
								// 虚拟通道编号
								virtualWapChannel.ChannelID = ch
										.getChannelSno() * 1000 + (m + 1);
								virtualWapChannel.ExtWapVar = "CT=0@@StCnt=0@@FeeCode=0";
								virtualWapChannel.FeeOKFlag = "";
								virtualWapChannel.FeeTipInfo = "";
								virtualWapChannel.FeeType = ch
										.getChannelTypeCode();
								virtualWapChannel.SendCnt = 1;
								virtualWapChannel.SendInterval = ch
										.getClientSendInterval();
								virtualWapChannel.ValidateStep = Constants.ValidateWapType.NoNeedValidate;
								virtualWapChannel.ValidateEndKey = "";
								virtualWapChannel.ValidateFindKeys = "";
								virtualWapChannel.WapFeeUrl = entryUrl;
								virtualWapChannel.FeeStep = new FetchStep[steps
										.size()];
								for (int q = 0; q < virtualWapChannel.FeeStep.length; q++) {
									FetchStep fs = new FetchStep();
									fs.FetchBy = Constants.FeeStepBy.BY_CLIENT;
									fs.FindKeys = (String) steps.get(q).get(
											"findkey");
									fs.EndKey = (String) steps.get(q).get(
											"endkey");
									;
									virtualWapChannel.FeeStep[q] = fs;
								}

								waplist.add(virtualWapChannel);

							}
						} catch (Exception ex3) {
							log.error("", ex3);
						}
					}

					wap.ChannelID = ch.getChannelSno();
					wap.ExtWapVar = "CT=0@@StCnt=1@@FeeCode=" + ch.getFeeCode();
					wap.FeeOKFlag = StringUtils.trim(chwap.getFeeOKFlagList());
					wap.FeeTipInfo = StringUtils.trim(ch.getFeeTipInfo());
					wap.FeeType = ch.getChannelTypeCode();
					wap.SendCnt = sendCnt;
					wap.SendInterval = ch.getClientSendInterval();
					wap.ValidateStep = chwap.getValidateStep().byteValue();
					if (wap.ValidateStep == Constants.ValidateWapType.NoNeedValidate) {
						wap.ValidateEndKey = "";
						wap.ValidateFindKeys = "";
					} else if (wap.ValidateStep == Constants.ValidateWapType.NeedClientPicValidate) {
						wap.ValidateEndKey = chwap.getValidateEndKey();
						wap.ValidateFindKeys = chwap.getValidateFindKeyList();
					} else {
						wap.ValidateStep = (byte) Constants.ValidateWapType.NoNeedValidate;
						wap.ValidateEndKey = "";
						wap.ValidateFindKeys = "";
					}
					wap.WapFeeUrl = ch.getDestAddr();
					wap.FeeStep = ParseFetch.analyse(chwap.getWAPFetchStrs());
					waplist.add(wap);

					cur.setSendCmd("WAP");
					cur.setSendCnt(wap.SendCnt);
					cur.setUseCnt(wap.SendCnt);
					cur.setSendInterval(wap.SendInterval);
					cur.setDestAddr(wap.WapFeeUrl);
					ChannelUserSelectRecordDao.insert(cur);

					cudc.setChannelID(ch.getChannelSno());
					cudc.setUseCnt(wap.SendCnt);
					cumc.setChannelID(ch.getChannelSno());
					cumc.setUseCnt(wap.SendCnt);
				} else if (ch.getChannelBigType() == Constants.ChannelBigType.IVR) {
					ChannelIvr chivr = (ChannelIvr) chex;
					Float hangUpRate = chivr.getHangUpRate();
					boolean virtualHangUpChannel = false;
					try {
						if (hangUpRate != null && hangUpRate > 0) {
							Integer RandomHandUpNumber = (int) (hangUpRate * 100);
							if (RandomHandUpNumber != null
									&& RandomHandUpNumber > 0) {
								int ran = RandomUtils.nextInt(100);
								if (ran < RandomHandUpNumber) {// 如果范围在里面，就虚拟出一个挂机通道
									virtualHangUpChannel = true;
								}
							} else {
								virtualHangUpChannel = false;
							}
						}
					} catch (Exception ex4) {
						log.error("", ex4);
					}

					if (virtualHangUpChannel) {
						ChannelIVR ivr = new ChannelIVR();
						ivr.ChannelID = ch.getChannelSno() * 1000;
						ivr.ExtIvrVar = "CT=0@@StCnt=0@@UseCnt=0"
								+ "@@FeeCode=" + ch.getFeeCode();
						ivr.FeeTipInfo = ch.getFeeTipInfo();
						ivr.FeeType = ch.getChannelTypeCode();
						ivr.IvrFeeTel = ch.getDestAddr();
						if (chivr.getFeeMinTimeLen() > 0) {// 模拟挂机

							ivr.SendCnt = RandomUtils.nextInt(chivr
									.getStartFeeTimeLen()
									+ chivr.getFeeMinTimeLen());
						} else {
							ivr.SendCnt = 1;
							log.error("通道ID=" + ivr.ChannelID + "有效时长不应该设置为0！");
						}
						ivr.KeySeries = "";
						ivr.SendInterval = ch.getClientSendInterval()
								+ RandomUtils.nextInt(10);
						ivrlist.add(ivr);
					}
					for (int n = 0; n < sendCnt; n++) {
						ChannelIVR ivr = new ChannelIVR();
						ivr.ChannelID = ch.getChannelSno();
						ivr.ExtIvrVar = "CT=0@@StCnt=1@@UseCnt=1"
								+ "@@FeeCode=" + ch.getFeeCode();
						ivr.FeeTipInfo = ch.getFeeTipInfo();
						ivr.FeeType = ch.getChannelTypeCode();
						ivr.IvrFeeTel = ch.getDestAddr();
						// 开始计费时长+最短有效计费时长+Rnd*10,
						ivr.SendCnt = chivr.getStartFeeTimeLen()
								+ chivr.getFeeMinTimeLen()
								+ (RandomUtils.nextInt(10) + 1); // 通话时长
						// 解析按键序列：
						String keySeries = chivr.getKeySeries();
						String[] striesStrs = keySeries.split(",");
						striesStrs = ArrayUtils.trim(striesStrs);
						String afterkeySeries = "";
						if (striesStrs.length > 0) {
							// 随机按键的个数
							int ranlen = RandomUtils.nextInt(striesStrs.length) + 1;
							for (int f = 0; f < ranlen; f++) {
								String str = striesStrs[f];
								int base = (ivr.SendCnt - chivr
										.getStartFeeTimeLen()) * 1000;
								int KeyTime = RandomUtils
										.nextInt((base / ranlen)) + 1;
								if (f == 0) {
									KeyTime = KeyTime
											+ chivr.getStartFeeTimeLen() * 1000;
									afterkeySeries = KeyTime + "|" + str;
								} else {
									afterkeySeries = afterkeySeries + ","
											+ KeyTime + "|" + str;
								}
							}
						}
						ivr.KeySeries = afterkeySeries;

						ivr.SendInterval = ch.getClientSendInterval()
								+ RandomUtils.nextInt(10);
						ivrlist.add(ivr);
						cur.setSendCmd("IVR");
						cur.setSendCnt(ivr.SendCnt);// 发送时长
						cur.setUseCnt(1);
						cur.setSendInterval(ivr.SendInterval);
						cur.setDestAddr(ch.getDestAddr());
						ChannelUserSelectRecordDao.insert(cur);
						ChannelMoMatchDao.insert(cmm);
					}

					cudc.setChannelID(ch.getChannelSno());
					cudc.setUseCnt(sendCnt);
					cumc.setChannelID(ch.getChannelSno());
					cumc.setUseCnt(sendCnt);
					if (StringUtils.isEmpty(this.Mobile)) {
						ServiceCoUserDoublePrecisionDao.Cumsum(scd);
					}
				} else {
				}
				ChannelUserDayConsumeDao.InsertOrUpdate(cudc);
				ChannelUserMonthConsumeDao.InsertOrUpdate(cumc);
				// 37 修改:黄敬锋2012-02-14=========增加针对一个用户只能终身使用一次的通道记录
				if (ch.getOnlyUseOnceForEverUser() == Constants.OnlyUseOnceForEverUser.YES) {
					ChannelOnlyUseOnceForImsi couofi = new ChannelOnlyUseOnceForImsi();
					couofi.setChannelID(ch.getChannelSno());
					couofi.setImsi(IMSI);
					couofi.setUpdateTime(curTime);
					ChannelOnlyUseOnceForImsiDao.InsertOrUpdate(couofi);
				}

				// 设置met的相关参数,修改：孙超进 2012-02-29，以前的代码有bug，而且位置提到这里来
				met.setCurDayUseChannelCnt(met.getCurDayUseChannelCnt() + 1);// 更新用户日扣费次数
				met.setCurMonthFee(met.getCurMonthFee());
				met.setCurMonthUseChannelCnt(met.getCurMonthUseChannelDayCnt() + 1);// 更新用户月扣费次数
				Date lastUseChanneldate = met.getLastUseChannelTime();
				if (lastUseChanneldate == null) {
					met.setCurMonthUseChannelDayCnt(1);
				} else {
					DateTime dt = new DateTime(lastUseChanneldate);
					DateTime dtcur = new DateTime(curTime);
					if (!dt.equalWithSameDay(dtcur)) {// 如果是不在同一天
						met.setCurMonthUseChannelDayCnt(met
								.getCurMonthUseChannelDayCnt() + 1);
					}
				}
				met.setLastUseChannelTime(curTime);
				met.setDoFee(Constants.DoFee.UseChannel);
			}

			// 三种通道指令
			res.wap = waplist.toArray(new ChannelWAP[0]);
			res.sms = smslist.toArray(new ChannelSMS[0]);
			// 指令里含有@@都转换为空格
			for (int i = 0; i < res.sms.length; i++) {
				// 过滤短信指令，如果指令里存在@@字符则变成空格
				res.sms[i].SmsFeeCmd = StringUtils.trim(res.sms[i].SmsFeeCmd)
						.replaceAll("@@", " ");
			}
			res.ivr = ivrlist.toArray(new ChannelIVR[0]);
			if (res.wap.length == 0 && res.sms.length == 0
					&& res.ivr.length == 0) {// 没有通道
				res.SmsCloseMt = (byte) Constants.CloseMt.NoNeedCloseMt;
				res.SmsCloseTime = 0;
			} else {
				res.SmsCloseMt = service.getIsClostMt().byteValue();
				// 38 构造屏蔽信息
				if (service.getIsClostMt() == Constants.CloseMt.NeedClostMt) {
					// ========查找屏蔽信息
					BaseClientSmsClose closeInfo = BaseClientSmsCloseDao
							.getClientSmsCloseInfoBy(provinceID,
									this.PhoneFactoryName);
					res.SmsCloseTime = ChannelProvinceMtCloseTimeLenDao
							.getMtCloseTimeLenBy(provinceID);
					if (null != closeInfo) {
						res.SmsCloseKeyword = closeInfo.getCloseKeys();
						res.SmsCloseSpNumber = closeInfo
								.getCloseChannelPrefixs();
						res.SmsOpenSpNumber = closeInfo.getOpenChannelPrefixs();
					}
				} else if (service.getIsClostMt() == Constants.CloseMt.NoNeedCloseMt) {
					res.SmsCloseTime = 0;
				} else {
					res.SmsCloseMt = (byte) Constants.CloseMt.NoNeedCloseMt;
					res.SmsCloseTime = 0;
				}
			}
			ExtRespVar extrv = new ExtRespVar();
			extrv.Mobile = StringUtils.trim(this.Mobile);
			extrv.UseCanSupport = useCanSupport;
			res.ExtRespVar = ObjectUtils.toJsonString(extrv);
			// 39增加一个ChannelUserSelectRecCloseInfo表来记录成功选通道的详情
			ChannelUserSelectRecCloseInfo curci = new ChannelUserSelectRecCloseInfo();
			curci.setExtRespVar(res.ExtRespVar);
			curci.setFeeID(res.FeeID);
			curci.setSmsCloseKeyword(res.SmsCloseKeyword);
			curci.setSmsCloseMt((int) res.SmsCloseMt);
			curci.setSmsCloseSpNumber(res.SmsCloseSpNumber);
			curci.setSmsCloseTime(res.SmsCloseTime);
			curci.setSmsOpenSpNumber(res.SmsOpenSpNumber);
			ChannelUserSelectRecCloseInfoDao.insert(curci);

			// 实现跳转
		} catch (Exception e) {
			log.error("", e);
			return result = res = FeeUtil.getDefault(
					Constants.FeeStatus.UnknownError_1001, e.getMessage());
		} finally {
			this.endDeal(met, result, cityID, provinceID, curTime,
					carrier.getValue(), start);
		}
		return result;

	}

	/**
	 * 
	 * @param met
	 * @param result
	 * @param cityID
	 * @param provinceID
	 * @param curTime
	 * @param carrier
	 */
	public void endDeal(MobileExt met, Object result, Integer cityID,
			Integer provinceID, Date curTime, String carrier, long start) {

		MobileExtDao.InsertOrUpdate(met);

		// 40 设置ChannelFeeReqRespRecord
		ChannelFeeReqRespRecord cfrr = new ChannelFeeReqRespRecord();
		cfrr.setRequestCanSupport(this.CanSupport);
		cfrr.setRequestCarrier(carrier);
		cfrr.setRequestCityID(cityID);
		cfrr.setRequestExtVar(this.ExtVar);
		cfrr.setRequestFeeMode(this.FeeMode);
		cfrr.setRequestFeePolicy(this.FeePolicy);
		cfrr.setRequestGatewayIP(this.getGateWayIP());
		cfrr.setRequestGatewayKW(this.getGateWayKey());
		cfrr.setRequestIMSI(this.IMSI);
		cfrr.setRequestMobile(this.Mobile);
		cfrr.setRequestPacketID(PacketID);
		cfrr.setRequestPayFee(this.PayFee);
		cfrr.setRequestPhoneFactoryName(this.PhoneFactoryName);
		cfrr.setRequestPlatform(this.Platform);
		cfrr.setRequestProtocol(this.Protocol);
		cfrr.setRequestProvinceID(provinceID);
		cfrr.setRequestRequestFrom(this.RequestFrom);
		cfrr.setRequestServiceCoID(this.COID);
		cfrr.setRequestSingleMaxFee(this.SingleMaxFee);
		cfrr.setRequestSmsCenter(this.SmsCenter);
		cfrr.setRequestTime(curTime);
		cfrr.setRequestVer(this.Ver);
		cfrr.setRequestVmVer(this.VmVer);
		cfrr.setRequestChannelMaxNum(this.ChannelMaxNum);
		cfrr.setRequestQueryChannel(this.QueryChannel);
		if (result instanceof Res010001) {
			Res010001 fres = (Res010001) result;
			cfrr.setResponseContent(ObjectUtils.toString(ObjectUtils
					.CloneWithDeep(fres, byte[].class)));
			cfrr.setResponseFeeID(fres.FeeID);
			cfrr.setResponseFeeStatus(fres.FeeStatus);
			cfrr.setResponseMessage(fres.Message);
			cfrr.setResponseProtocol(fres.Protocol);
			cfrr.setResponseStatus((int) fres.Status);
			cfrr.setResponseThisFee(fres.ThisFee);

		} else if (result instanceof Res010009) {
			Res010009 fres = (Res010009) result;
			Res010009 resnew = new Res010009();
			resnew.Protocol = fres.Protocol;
			resnew.Packet = new byte[0];
			resnew.Message = fres.Message;
			resnew.Status = fres.Status;
			cfrr.setResponseContent(ObjectUtils.toString(resnew));
			cfrr.setResponseFeeID("");
			cfrr.setResponseFeeStatus(Constants.FeeStatus.UpdateClientLibVer);
			cfrr.setResponseMessage(fres.Message);
			cfrr.setResponseProtocol(fres.Protocol);
			cfrr.setResponseStatus((int) fres.Status);
		} else if (result instanceof Res010005) {
			Res010005 fres = (Res010005) result;
			cfrr.setResponseContent(ObjectUtils.toString(fres));
			cfrr.setResponseFeeID("");
			cfrr.setResponseFeeStatus(Constants.FeeStatus.LetClientSendGetPhone);
			cfrr.setResponseMessage(fres.Message);
			cfrr.setResponseProtocol(fres.Protocol);
			cfrr.setResponseStatus((int) fres.Status);
		}
		long timeLen = System.currentTimeMillis() - start;
		cfrr.setResponseTimeLen((int) timeLen);
		ChannelFeeReqRespRecordDao.add(cfrr);
	}

	public static void main(String[] args) throws Exception {
		System.out.println("VM CanSupport@UDO CanSupport");
		String[] strs = StringUtils.split("@1345", "@");
		System.out.println(ArrayUtils.toJavascriptString(strs));

		System.out.println(" , 22".matches("\\d+( *, *\\d+)*"));
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		System.out.println("选择的通道：" + ObjectUtils.toJsonString(list));
	}

	@Override
	public String validate() throws Exception {

		// if(StringUtils.isEmpty(this.IMSI)) {
		// this.IMSI=Constants.DefaultIMSI;
		// }

		return null;
	}

	/**
	 * 合作业务ID，后台通过此id可以找到对应的产品，产品的概念：好玩吧 ，哈密瓜等
	 */
	public Integer COID;
	/**
	 * 包id
	 */
	public String PacketID;
	/**
	 * 版本号id，函数库的版本号
	 */
	public Integer Ver;
	/**
	 * 平台
	 */
	public String Platform;
	/**
	 * 虚拟机版本号
	 * 
	 */
	public Integer VmVer;
	/**
	 * 手机卡串号，获取不到送空字符串
	 * 
	 */
	public String IMSI;
	/**
	 * 已知手机号码，允许为空
	 */
	public String Mobile;
	/**
	 * 短信中心号码，允许为空
	 */
	public String SmsCenter;
	/**
	 * 付费金额（单位：分）
	 */
	public Integer PayFee;
	/**
	 * 需要计费中心能够返回的计费类型,用于支持应用对于付费通道的偏向性选择,客户端可以支持多种计费类型，以逗号分开。 0:表示全部支持 1：SMS
	 * 2：MMS 等等
	 */
	public String CanSupport;
	/**
	 * 1-请求本接口来自客户端，
	 * 2-请求本接口来自服务器,如果是来做客户端请求模式，则Carrier，GatewayIP，GatewayKW为空字符串,
	 * 如果是服务器请求模式，则Carrier，GatewayIP，GatewayKW必须填
	 * 
	 * @see SysEnum.RequestFrom
	 */
	public Integer RequestFrom;
	/**
	 * 单次扣费资费限制，单位分，通过此参数，服务器选择通道时，不能选择超过此业务资费的通道代码。 计费中心服务器优先使用此参数选择满足此条件的通道。
	 * 此参数RequestFrom=2时使用，由业务服务器调用计费中心使用， 当RequestFrom=1时，不用提交此参数
	 */
	public Integer SingleMaxFee;
	/**
	 * 运营商,1:移动，2:联通，3:网通，4:电信，5:铁通; 此参数RequestFrom=2时使用，由业务服务器调用计费中心使用，
	 * 当RequestFrom=1时，不用提交此参数
	 * 
	 * @see SysEnum.Carrier
	 */
	public Integer Carrier;
	/**
	 * WAP网关IP，如果是由合作方后台访问需要将客户端的WAP网关IP送过来作判断，来源于REMOTE_ADDR参数,
	 * 此参数RequestFrom=2时使用，由业务服务器调用计费中心使用， 当RequestFrom=1时，不用提交此参数
	 */
	public String GatewayIP;
	/**
	 * WAP网关特征字，如果是由合作方后台访问本接口需要将客户端的WAP网关特征字送过来作判断，来源于HTTP_VIA参数,
	 * 此参数RequestFrom=2时使用，由业务服务器调用计费中心使用
	 */
	public String GatewayKW;
	/**
	 * 厂商简称，用于解决厂商的些特殊的要求，如短信屏蔽
	 */
	public String PhoneFactoryName;
	/**
	 * 扣费模式： 1：月费扣费 2：补扣扣费 3：下载扣费 4：游戏扣费 5：虚拟币充值 100：未知扣费模式
	 * 
	 * @see SysEnum.FeeMode
	 */
	public Integer FeeMode;
	/**
	 * 最大通道条数（用于兼容老系统）
	 */
	public Integer ChannelMaxNum;
	/**
	 * 0:正常获取通道 1：查询是否有可用通道.
	 */
	public Integer QueryChannel;
	/**
	 * 固定4位数，从右到左算。
	 * 
	 * 第1位：为烂通道选择策略。如果设置为1，表示计费中心选择烂通道，例如：0001； 如果设置为0，计费中心按默认算法来。
	 * 
	 * 第2位:
	 * 优先使用IVR+SMS通道策略。如果设置为1，表示计费中心优先选择IVR+SMS；如果设置为0，表示一般算法，即IVR+SMS+WAP平等考虑
	 * 。例如：0010。
	 * 
	 * 第一位和第二位可以同时设置，例如 0011，表示即设置了烂通道策略和优先使用IVR+SMS通道策略
	 * 
	 * 注释：烂通道选择策略，以实现投诉可能较高的用户扣费的控制在风险较小的通道（选择支持老用户未激活的通道）
	 * 
	 * 此字段内部使用，提供给第三方的文档不会有此参数
	 * 
	 * 
	 * @see SysEnum.FeePolicy
	 */
	public String FeePolicy;
	/**
	 * 扩展参数，具体定义规则由“调用方”来定，计费中心送上行的时候， 把此参数传到第三方业务平台的上行记录表， 由第三方业务平台来解释具体含义。例如：
	 * mobileid=123&packetid=4567
	 */
	public String ExtVar;
	/**
	 * 是否用于pc模拟器测试 1：是 0：否
	 */
	public Integer Test = 0;

	/**
	 * 构造函数
	 */
	public Pro010001() {
		this.Protocol = "010001";
	}

}
